/**
 *
 *Open RingBuffer for tool use.
 *
 * @open_ringbuffer.c
 *
 * $Author: ycl $
 * $Date: 2023-7-31 $
 * $Revision: 001 $
 *
 * @remarks
 * 2023-7-31：str_buffer base thought ref. from: https://gitee.com/netube/RingBuffer/blob/main/ring_buffer.c
 */

#include "open_ringbuffer.h"

static oprb_ringbuffer ringbuffer = {0};

#ifdef OPRB_DEBUG
static void oprb_debugprint()
{
    printf("log_item_writer = %d \n", ringbuffer.log_item_writer);
    printf("log_item_reader = %d \n", ringbuffer.log_item_reader);
    printf("log_item_used_len = %d \n", ringbuffer.log_item_used_len);
    printf("log_item[0].str_len = %d \n", ringbuffer.log_item[0].str_len);
    printf("log_item[1].str_len = %d \n", ringbuffer.log_item[1].str_len);
    printf("log_item[2].str_len = %d \n", ringbuffer.log_item[2].str_len);
    printf("log_item[3].str_len = %d \n", ringbuffer.log_item[3].str_len);

    printf("str_buffer_writer = %d \n", ringbuffer.str_buffer_writer);
    printf("str_buffer_reader = %d \n", ringbuffer.str_buffer_reader);
    printf("str_buffer_used_len = %d \n", ringbuffer.str_buffer_used_len);

    printf("\n");
}

#endif

#ifdef OPRB_UTEST
oprb_ringbuffer oprb_get_ringbuffer()
{
    return ringbuffer;
}
#endif

/**
********************************************************************************
  * @explanation oprb_writeline 写一行日志
  * @param in_str[in] 写入日志的字符串指针
  * @return > 0:写入日志字符长度； < 0: 错误码
  * @remarks Important: 1.如果ring buffer满，返回错误码;
  * 2.本函数写日志内部不自动添加换行符，使用者在外部根据需要自行添加.
 ********************************************************************************
*/
int oprb_writeline(char* in_str)
{
    int len = strlen(in_str);
        
    if(len <= 0) /*不允许写入空字符串*/
    {
        return OPRB_FAILED;
    }

    if(ringbuffer.log_item_used_len >= OPRB_LOG_ITEM_MAX_LEN)
    {
        return OPRB_LOG_ITEM_FULL;
    }

    if((ringbuffer.str_buffer_used_len + len) > OPRB_STR_BUFFER_MAX_LEN)
    {
        return OPRB_STR_BUFFER_FULL;
    }
    
    ringbuffer.log_item[ringbuffer.log_item_writer].str_len = len;
    if(ringbuffer.log_item_writer >= OPRB_LOG_ITEM_MAX_LEN -1){
        ringbuffer.log_item_writer = 0;
    }else{
        ringbuffer.log_item_writer +=1;
    }
    ringbuffer.log_item_used_len +=1;

    int part = OPRB_STR_BUFFER_MAX_LEN - ringbuffer.str_buffer_writer;
    if(part >= len)
    {
        memcpy(ringbuffer.str_buffer + ringbuffer.str_buffer_writer, in_str, len);
        ringbuffer.str_buffer_writer += len;        
    }
    else
    {        
        memcpy(ringbuffer.str_buffer + ringbuffer.str_buffer_writer, in_str, part);
        memcpy(ringbuffer.str_buffer, in_str + part, len-part);
        ringbuffer.str_buffer_writer = len-part;
    }
    ringbuffer.str_buffer_used_len += len;

#ifdef OPRB_DEBUG
    oprb_debugprint();
#endif
    return len;
}

/**
********************************************************************************
  * @explanation oprb_readline 读一行日志
  * @param out_str[out] 读出日志存放的buff指针
  * @param len[in]    读出日志存放的buff长度
  * @return > 0:读出日志的字符长度； < 0: 错误码
  * @remarks Important: 1.如果ring buffer空，返回错误码;
 ********************************************************************************
*/
int oprb_readline(char *out_str, int len)
{
    if(ringbuffer.log_item_used_len == 0)
    {        
        return OPRB_LOG_ITEM_EMPTY;
    }

    if(ringbuffer.log_item[ringbuffer.log_item_reader].str_len > len -1)
    {
        return OPRB_LOG_LEN_OVER_RECV_BUFF_LEN;
    }

    int read_log_len = ringbuffer.log_item[ringbuffer.log_item_reader].str_len;
    int part = OPRB_STR_BUFFER_MAX_LEN - ringbuffer.str_buffer_reader;
    if(part >= read_log_len)
    {
        memcpy(out_str, ringbuffer.str_buffer + ringbuffer.str_buffer_reader, read_log_len);
        ringbuffer.str_buffer_reader += read_log_len;
    }
    else
    {
        memcpy(out_str, ringbuffer.str_buffer + ringbuffer.str_buffer_reader, part);
        memcpy(out_str + part, ringbuffer.str_buffer, read_log_len -part);
        ringbuffer.str_buffer_reader = read_log_len -part;
    }
    ringbuffer.str_buffer_used_len -= read_log_len;

    if(ringbuffer.log_item_reader >= OPRB_LOG_ITEM_MAX_LEN -1){
        ringbuffer.log_item_reader = 0;
    }else{
        ringbuffer.log_item_reader +=1;
    }
    ringbuffer.log_item_used_len -=1;

    out_str[read_log_len] = 0; //最后多写入一个字符串结束符进去

#ifdef OPRB_DEBUG
    oprb_debugprint();
#endif
    return read_log_len;
}

